package hu.mapro.gwtui.gxt.client.recordseditor.requestfactory;

import hu.mapro.gwtui.client.Action;
import hu.mapro.gwtui.gxt.client.fieldseditor.RequestContextInitializer;

import java.util.List;

import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.FanoutReceiver;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.RequestContext;

public class PersistenceAdapter<T extends BaseProxy> implements
		hu.mapro.gwtui.gxt.client.recordseditor.PersistenceInterface<T, RequestContextInitializer> {

	Interface<T> operations;

	public PersistenceAdapter(
			Interface<T> operations
	) {
		super();
		this.operations = operations;
		newRequestContext();
	}

	RequestContext currentRequestContext;
	
	public RequestContext getCurrentRequestContext() {
		return currentRequestContext;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public <Q> Q create(Class<Q> clazz) {
		Class erasure = clazz;
		return (Q) currentRequestContext.create(erasure);
	}

	@Override
	public void newEditingContext() {
		newRequestContext();
	}

	@Override
	public void list(final Receiver<List<T>> receiver) {
		operations.list(newRequestContextReceiver(receiver));
	}

	@Override
	public void persist(T object, Receiver<Void> receiver) {
		operations.persist(object, newRequestContextReceiver(receiver));
	}

	@Override
	public void merge(T object, Receiver<T> receiver) {
		operations.merge(object, newRequestContextReceiver(receiver));
	}

	@Override
	public void delete(List<T> object, Receiver<Void> receiver) {
		operations.remove(object, newRequestContextReceiver(receiver));
	}
	
	protected <V> Receiver<V> newRequestContextReceiver(
			Receiver<V> receiver) {
		FanoutReceiver<V> r = new FanoutReceiver<V>();
		r.add(new Receiver<V>() {
			@Override
			public void onSuccess(V response) {
				newRequestContext();
			}
		});
		r.add(receiver);
		return r;
	}

	private void newRequestContext() {
		currentRequestContext = operations.newRequestContext();
	}

	RequestContextInitializer initializer = new RequestContextInitializer() {
		@Override
		public RequestContext getCurrentRequestContext() {
			return currentRequestContext;
		}
	};
	
	@Override
	public RequestContextInitializer getInitializer() {
		return initializer;
	}

	@Override
	public void addChangeHandler(Action handler) {
		operations.addChangeHandler(handler);
	}
	
}